﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BulletSharp;
using Microsoft.Xna.Framework;

namespace KinectGame
{
    public class LevelTimer
    {
        RigidBody bottom, left, right, front, back;
        BoxShape bottomShape, leftShape, rightShape, frontShape, backShape;
        Matrix bottomPosition, leftPosition, rightPosition, frontPosition, backPosition;
        Matrix bottomRotation, leftRotation, rightRotation, frontRotation, backRotation;
        List<GameObject> timerObjects = new List<GameObject>();

        Vector3 position;
        Vector3 rotation;

        TimeSpan newTimerObjectTimeSpan;
        DateTime lastNewTimerObject = DateTime.Now;

        RigidBodyConstructionInfo rbci;

        public Vector3 Rotation
        {
            get { return rotation; }
            set 
            { 
                rotation = value;

                Matrix newRotation = Matrix.CreateRotationX(MathHelper.ToRadians(rotation.X)) *
                    Matrix.CreateRotationY(MathHelper.ToRadians(rotation.Y)) *
                    Matrix.CreateRotationZ(MathHelper.ToRadians(rotation.Z));
                Matrix newTranslation = Matrix.CreateTranslation(position);

                bottom.WorldTransform = bottomRotation * newRotation * bottomPosition * newTranslation;
                left.WorldTransform = leftRotation * newRotation * leftPosition * newTranslation;
                right.WorldTransform = rightRotation * newRotation * rightPosition * newTranslation;
                front.WorldTransform = frontRotation * newRotation * frontPosition * newTranslation;
                back.WorldTransform = backRotation * newRotation * backPosition * newTranslation;
            }
        }

        public Vector3 Position
        {
            get { return position; }
            set 
            { 
                position = value;

                Matrix newRotation = Matrix.CreateRotationX(MathHelper.ToRadians(rotation.X)) *
                    Matrix.CreateRotationY(MathHelper.ToRadians(rotation.Y)) *
                    Matrix.CreateRotationZ(MathHelper.ToRadians(rotation.Z));
                Matrix newTranslation = Matrix.CreateTranslation(position);

                bottom.WorldTransform = bottomRotation * newRotation * bottomPosition * newTranslation;
                left.WorldTransform = leftRotation * newRotation * leftPosition * newTranslation;
                right.WorldTransform = rightRotation * newRotation * rightPosition * newTranslation;
                front.WorldTransform = frontRotation * newRotation * frontPosition * newTranslation;
                back.WorldTransform = backRotation * newRotation * backPosition * newTranslation;
            }
        }

        public List<GameObject> SecondsObject
        {
            get { return timerObjects; }
        }

        public LevelTimer(TimeSpan timeBetweeneObjects)
        {
            bottomShape = new BoxShape(2, 1, 2);
            bottomPosition = Matrix.CreateTranslation(Vector3.Down);
            bottomRotation = Matrix.Identity;
            RigidBodyConstructionInfo rbci = new RigidBodyConstructionInfo(0, new DefaultMotionState(bottomRotation * bottomPosition), bottomShape);
            bottom = new RigidBody(rbci);
            

            leftShape = new BoxShape(3, 5, 1);
            leftPosition = Matrix.CreateTranslation(new Vector3(-3, 5, 0));
            leftRotation = Matrix.CreateRotationY(MathHelper.ToRadians(90));
            rbci = new RigidBodyConstructionInfo(0, new DefaultMotionState(leftRotation * leftPosition), leftShape);
            left = new RigidBody(rbci);
            

            rightShape = new BoxShape(3, 5, 1);
            rightPosition = Matrix.CreateTranslation(new Vector3(3, 5, 0));
            rightRotation = Matrix.CreateRotationY(MathHelper.ToRadians(90));
            rbci = new RigidBodyConstructionInfo(0, new DefaultMotionState(rightRotation * rightPosition), rightShape);
            right = new RigidBody(rbci);
            

            frontShape = new BoxShape(3, 5, 1);
            frontPosition = Matrix.CreateTranslation(new Vector3(0, 5, 3));
            frontRotation = Matrix.Identity;
            rbci = new RigidBodyConstructionInfo(0, new DefaultMotionState(frontRotation * frontPosition), frontShape);
            front = new RigidBody(rbci);
            

            backShape = new BoxShape(3, 5, 1);
            backPosition = Matrix.CreateTranslation(new Vector3(0, 5, -3));
            backRotation = Matrix.Identity;
            rbci = new RigidBodyConstructionInfo(0, new DefaultMotionState(backRotation * backPosition), backShape);
            back = new RigidBody(rbci);

            for (int i = 0; i < 20; i++)
            {
                SphereShape shape = new SphereShape(1.1f);
                GameObject go = new GameObject(Game.models["clock"], Vector3.One, Vector3.Zero, Vector3.Zero, 10.0f, shape);
                go.Activate();
                timerObjects.Add(go);
                go.Visible = false;
            }

            newTimerObjectTimeSpan = timeBetweeneObjects;
        }

        int counter = 0;

        public void Update()
        {
            if (DateTime.Now - lastNewTimerObject > newTimerObjectTimeSpan && counter < 20)
            {
                Random r = new Random();
                Vector3 dropPos = position;
                dropPos.Y += 25;
                dropPos.X += ((float)r.NextDouble() - 0.5f)/2.0f;
                dropPos.Z += ((float)r.NextDouble() - 0.5f)/2.0f;

                GameObject go = timerObjects[counter];
                go.RigidBody.Translate(dropPos);
                go.Visible = true;
                Game.World.AddRigidBody(go.RigidBody);
                lastNewTimerObject = DateTime.Now;

                counter++;
            }
        }

        public void Start()
        {
            Game.World.AddRigidBody(bottom);
            Game.World.AddRigidBody(left);
            Game.World.AddRigidBody(right);
            Game.World.AddRigidBody(front);
            Game.World.AddRigidBody(back);
            lastNewTimerObject = DateTime.Now;
            counter = 0;
        }

        public void Clear()
        {
            foreach (var go in timerObjects)
            {
                if (go.RigidBody != null)
                {
                    Game.World.RemoveRigidBody(go.RigidBody);
                }
                
                go.RigidBody.WorldTransform = Matrix.Identity;
                go.Activate();
                go.Visible = false;
            }

            Game.World.RemoveRigidBody(bottom);
            Game.World.RemoveRigidBody(left);
            Game.World.RemoveRigidBody(right);
            Game.World.RemoveRigidBody(front);
            Game.World.RemoveRigidBody(back);
        }
    }
}
